#ifndef DMA_H
#define DMA_H
/*
 * These are the memory types, defined to be compatible with
 * pre-ARMv6 CPUs cacheable and bufferable bits:   XXCB
 */
#include <asm-arm/pgtable.h>
#include <asm-arm/mm.h>
#include <asm-arm/page.h>
#define L_PTE_MT_UNCACHED	(0x00 << 2)	/* 0000 */
#define L_PTE_MT_BUFFERABLE	(0x01 << 2)	/* 0001 */
#define L_PTE_MT_WRITETHROUGH	(0x02 << 2)	/* 0010 */
#define L_PTE_MT_WRITEBACK	(0x03 << 2)	/* 0011 */
#define L_PTE_MT_MINICACHE	(0x06 << 2)	/* 0110 (sa1100, xscale) */
#define L_PTE_MT_WRITEALLOC	(0x07 << 2)	/* 0111 */
#define L_PTE_MT_DEV_SHARED	(0x04 << 2)	/* 0100 */
#define L_PTE_MT_DEV_NONSHARED	(0x0c << 2)	/* 1100 */
#define L_PTE_MT_DEV_WC		(0x09 << 2)	/* 1001 */
#define L_PTE_MT_DEV_CACHED	(0x0b << 2)	/* 1011 */
#define L_PTE_MT_MASK		(0x0f << 2)
	
	
typedef u32 dma_addr_t;
typedef unsigned long pgprot_t;
//typedef struct { unsigned long pgprot; } pgprot_t;
typedef unsigned gfp_t;
#define __pgprot(x)     (x)
#define pgprot_writecombine(prot) \
	__pgprot(prot | L_PTE_MT_BUFFERABLE)

#define CONSISTENT_DMA_SIZE 0x00200000
#define CONSISTENT_END	(0xffe00000)
#define CONSISTENT_BASE	(CONSISTENT_END - CONSISTENT_DMA_SIZE)
	

#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)
#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> 20 )

/*
 * These are the page tables (2MB each) covering uncached, DMA consistent allocations
 */
static pde_t *consistent_pte[NUM_CONSISTENT_PTES];

#define ISA_DMA_THRESHOLD	(0xffffffffUL)
	
/*
 * GFP bitmasks..
 *
 * Zone modifiers (see linux/mmzone.h - low three bits)
 *
 * Do not put any conditional on these. If necessary modify the definitions
 * without the underscores and use the consistently. The definitions here may
 * be used in bit comparisons.
 */
#define __GFP_DMA	((gfp_t)0x01u)
#define __GFP_HIGHMEM	((gfp_t)0x02u)
#define __GFP_DMA32	((gfp_t)0x04u)
	
#define PTRS_PER_PTE 512
	

/*
 * Physical DRAM offset.
 */
//#define PHYS_OFFSET	UL(0x00000000)
#define BUS_OFFSET	(0x00000000UL)

/*
 * Virtual view <-> DMA view memory address translations
 * virt_to_bus: Used to translate the virtual address to an
 *              address suitable to be passed to set_dma_addr
 * bus_to_virt: Used to convert an address for DMA operations
 *              to an address that the kernel can use.
 */
#define __virt_to_bus(x)	(x - PAGE_OFFSET + BUS_OFFSET)
#define __bus_to_virt(x)	(x - BUS_OFFSET + PAGE_OFFSET)
		
static inline dma_addr_t page_to_dma(/*struct device *dev,*/ struct page_info *page)
{
	return (dma_addr_t)__virt_to_bus((unsigned long)page_to_virt(page));
}

#define __pte(x)        (x)
#define pfn_pte(pfn,prot)	(__pte(((pfn) << PAGE_SHIFT) | prot))
/*
 * Conversion functions: convert a page and protection to a page entry,
 * and a page entry and page directory to the page they refer to.
 */
#define mk_pte(page,prot)	l1e_from_intpte(pfn_pte(page_to_pfn(page),prot))

//#define DEFINE_SPINLOCK(x)	spinlock_t x = __SPIN_LOCK_UNLOCKED(x)
void *dma_alloc_writecombine(/*struct device *dev, */size_t size, dma_addr_t *handle/*, gfp_t gfp*/);
#define MEMZONE_DMADOM 2
#define PGDIR_SHIFT 20
//typedef unsigned long pgprot_t;

#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)

/*
 * "Linux" PTE definitions.
 *
 * We keep two sets of PTEs - the hardware and the linux version.
 * This allows greater flexibility in the way we map the Linux bits
 * onto the hardware tables, and allows us to have YOUNG and DIRTY
 * bits.
 *
 * The PTE table pointer refers to the hardware entries; the "Linux"
 * entries are stored 1024 bytes below.
 */
#define L_PTE_PRESENT		(1 << 0)
#define L_PTE_FILE		(1 << 1)	/* only when !PRESENT */
#define L_PTE_YOUNG		(1 << 1)
#define L_PTE_BUFFERABLE	(1 << 2)	/* obsolete, matches PTE */
#define L_PTE_CACHEABLE		(1 << 3)	/* obsolete, matches PTE */
#define L_PTE_DIRTY		(1 << 6)
#define L_PTE_WRITE		(1 << 7)
#define L_PTE_USER		(1 << 8)
#define L_PTE_EXEC		(1 << 9)
#define L_PTE_SHARED		(1 << 10)	/* shared(v6), coherent(xsc3) */
#endif
